unit SystemManager;

{
  Generates all other systems and some utilities.
}

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, fgl, basicIO, basicGUI, basicAI, ExtCtrls, Forms,
  Dialogs, LCLType, Controls, FileProvider, logger;

type

  TBasicGUIClass = class of TBasicGUI;
  TBasicGUIList = specialize TFPGList<TBasicGUIClass>;

  TBasicAIClass = class of TBasicAI;
  TBasicAIList = specialize TFPGList<TBasicAIClass>;

  TBasicIOClass = class of TBasicIO;
  TBasicIOList = specialize TFPGList<TBasicIOClass>;

  { TSystemManager }

  TSystemManager = class
    private
      FGUI: TBasicGUI;
      FAI: TBasicAI;
      FIO: TBasicIO;
      FLog: TLog;
      FTimer: TTimer;
      FFileProvider: TFileProvider;
    private
      FGUI_Systems: TBasicGUIList;
      FIO_Systems: TBasicIOList;
      FAI_Systems: TBasicAIList;
      FSelectedGUI: integer;
      FSelectedIO: integer;
      FSelectedAI: integer;
    protected
      procedure TimerEvent (ASender: TObject);
    public
      procedure RegisterGUISystem(ASystem: TBasicGUIClass);
      procedure RegisterIOSystem(ASystem: TBasicIOClass);
      procedure RegisterAISystem(ASystem: TBasicAIClass);
      procedure CreateGUISystem(AID: integer);
      procedure CreateIOSystem(AID: integer);
      procedure CreateAISystem(AID: integer);
    public
      property SelectedGUI: integer read FSelectedGUI write FSelectedGUI;
      property SelectedIO: integer read FSelectedIO write FSelectedIO;
      property SelectedAI: integer read FSelectedAI write FSelectedAI;
      property GUI: TBasicGUI read FGUI;
      property GUI_Systems: TBasicGUIList read FGUI_Systems;
      property IO: TBasicIO read FIO;
      property IO_Systems: TBasicIOList read FIO_Systems;
      property AI: TBasicAI read FAI;
      property AI_Systems: TBasicAIList read FAI_Systems;
      property FileProvider: TFileProvider read FFileProvider;
      property Log: TLog read FLog;
      property Timer: TTimer read FTimer;
    public
      constructor Create;
      destructor Destroy; override;
    public
      procedure Setup;
      procedure ClearSystems;
      procedure WaitForGameStart;
      procedure InitializeGame;
    public
  end;

var
  GlobalSystemManager : TSystemManager;

implementation

uses
  StateMachine;

procedure TSystemManager.TimerEvent(ASender: TObject);
begin
  GlobalSystemManager.Log.Log('Timer event',TLSS_SystemManager);
  if assigned (FIO) and (GlobalStateMachine.State in [SS_AnalyzeGameState]) then
  begin
    FIO.Update;
    GlobalStateMachine.Transit(SS_ReactToGameState);
  end;
  if assigned(FGUI) then FGUI.UpdateGUI;
end;

procedure TSystemManager.RegisterGUISystem(ASystem: TBasicGUIClass);
begin
  FGUI_Systems.Add(ASystem);
end;

procedure TSystemManager.RegisterIOSystem(ASystem: TBasicIOClass);
begin
  FIO_Systems.Add(ASystem);
end;

procedure TSystemManager.RegisterAISystem(ASystem: TBasicAIClass);
begin
  FAI_Systems.Add(ASystem);
end;

procedure TSystemManager.CreateIOSystem(AID: integer);
begin
  FIO := FIO_Systems.Items[AID].Create;
end;

procedure TSystemManager.CreateAISystem(AID: integer);
begin
  FAI := FAI_Systems.Items[AID].Create;
end;

procedure TSystemManager.CreateGUISystem(AID: integer);
begin
  FGUI := FGUI_Systems.Items[AID].Create;
end;


constructor TSystemManager.Create;
begin
  FFileProvider:= TFileProvider.Create;
  FLog := TLog.Create(FileProvider.ProvideFile('SiedlerAI.log',FT_DebugOutput));

  FTimer := TTimer.Create(nil);
  FTimer.Interval := 2000;
  FTimer.OnTimer := @TimerEvent;
  FTimer.Enabled := true;

  FGUI_Systems := TBasicGUIList.Create;
  FIO_Systems  := TBasicIOList.Create;
  FAI_Systems  := TBasicAIList.Create;

  Log.Log('Create done',TLSS_SystemManager);
end;

destructor TSystemManager.Destroy;
begin
  FreeAndNil(FAI_Systems);
  FreeAndNil(FIO_Systems);
  FreeAndNil(FGUI_Systems);

  ClearSystems;

  FreeAndNil(FTimer);
  FreeAndNil(FLog);
  FreeAndNil(FFileProvider);
  inherited Destroy;
end;

procedure TSystemManager.Setup;
begin
  Log.Log('Creating GUI "'+GlobalSystemManager.GUI_Systems.Items[SelectedGUI].ClassName+'"',TLSS_SystemManager);
  GlobalSystemManager.CreateGUISystem(SelectedGUI);
  Log.Log('Creating IO"'+GlobalSystemManager.IO_Systems.Items[SelectedIO].ClassName+'"',TLSS_SystemManager);
  GlobalSystemManager.CreateIOSystem(SelectedIO);
  Log.Log('Creating AI"'+GlobalSystemManager.AI_Systems.Items[SelectedAI].ClassName+'"',TLSS_SystemManager);
  GlobalSystemManager.CreateAISystem(SelectedAI);
  FGUI.Show;
  Log.Log('Setup done',TLSS_SystemManager);
  GlobalStateMachine.Transit(SS_WaitingForGameStart);
end;

procedure TSystemManager.ClearSystems;
begin
  if assigned(FAI) then FreeAndNil(FAI);
  if assigned(FIO) then FreeAndNil(FIO);
  if assigned(FGUI)then FreeAndNil(FGUI);
end;

procedure TSystemManager.WaitForGameStart;
begin
  if MessageDlgPos('Click "Yes" when the game starts. Click "Abort" to abort.',
       mtConfirmation,[mbYes, mbAbort],0,
       Application.MainForm.Left,Application.MainForm.Top) = mrYes
  then
  begin
    GlobalStateMachine.transit(SS_InitializeGame);
  end else
  begin
    GlobalStateMachine.transit(SS_SelectSystems);
  end;
end;

procedure TSystemManager.InitializeGame;
begin
  Log.Log('Initializing game',TLSS_SystemManager);
  FIO.GatherInitiallyInfos;
  GlobalStateMachine.transit(SS_AnalyzeGameState)
end;

initialization
  GlobalSystemManager := TSystemManager.Create;

finalization
  GlobalSystemManager.Free;

end.

